#include "pf_parser.h"
#include "mid_ringbuf.h"
#include "util_api.h"
#include "pt_demo.h"

#define HEAD_LEN 5

ringbuf* rx_buf_stream;
int32_t max_frame_len=1024*1024*3;
uint32_t skip_nbyte_find_head=0;
uint32_t frame_cnt = 0;

uint64_t total_rx_dat_len_payload = 0;
uint32_t total_rx_pkt_num_payload = 0;
uint64_t total_rx_dat_len_payload_g = 0;
uint32_t total_rx_pkt_num_payload_g = 0;

int parser_exit=0;

pthread_mutex_t rx_buf_stream_mut=PTHREAD_MUTEX_INITIALIZER;

static unsigned char buf[FRAME_MAX_LEN];

/** Debug dump buffer length */
#define DBG_DUMP_BUF_LEN    256
/** Maximum number of dump per line */
#define MAX_DUMP_PER_LINE   16
/** Maximum data dump length */
#define MAX_DATA_DUMP_LEN   48

#define MIN(a, b)           ((a) < (b) ? (a) : (b))

#define DBG_PARSER 0

#define DBG_PARSER_GAP 3000 //ms
static uint32_t total_dat_len=0;
int32_t pretime=0,nowtime=0;
static uint32_t avrg_frame_len=1000;
uint32_t avg_dat_rate=0;
static uint32_t maxframe_len=0;
static uint16_t parser_skip_frm_cnt=0;

void PF_Parser_Buf_Print(char *prompt, uint8_t *buf, int len)
{
    int i;
    char dbgdumpbuf[DBG_DUMP_BUF_LEN];
    char *ptr = dbgdumpbuf;

    printf("%s: len=%d\n", prompt, len);
    for (i = 1; i <= MIN(len, MAX_DATA_DUMP_LEN); i++) {
        ptr += snprintf(ptr, 4, "%02x ", *buf);
        buf++;
        if (i % MAX_DUMP_PER_LINE == 0) {
            *ptr = 0;
            printf("%s\n", dbgdumpbuf);
            ptr = dbgdumpbuf;
        }
    }
    if (len % MAX_DUMP_PER_LINE) {
        *ptr = 0;
        printf("%s\n", dbgdumpbuf);
    }
}


int PF_Parser_Find_Sync_Head(uint32_t len, int offset)
{
    uint32_t i;
    uint32_t _offset;
    _offset = offset + rx_buf_stream->pread;

	// MID_UTIL_Print_Buf(&rx_buf_stream->pdata[MOD_RINGBUF_LEN(_offset)], len>20?20:len);

     for(i=0;i<len-4;i++)
     {
        if( rx_buf_stream->pdata[MOD_RINGBUF_LEN(_offset+i)]== 0xFF && \
            rx_buf_stream->pdata[MOD_RINGBUF_LEN(_offset+i+1)] == 0xA5 && \
            rx_buf_stream->pdata[MOD_RINGBUF_LEN(_offset+i+2)] == 0xAA && \
            rx_buf_stream->pdata[MOD_RINGBUF_LEN(_offset+i+3)] == 0x5A )
        	{
				if(rx_buf_stream->pdata[MOD_RINGBUF_LEN(_offset+i+4)]==0xFF)
           		{
           			skip_nbyte_find_head = i;
					rx_buf_stream->pdata[MOD_RINGBUF_LEN(_offset+i+4)];
				    return 0;
           		}
		 	}
     }
    skip_nbyte_find_head = len-4;
    return -1;
}

void PF_Parser_Find_Packet_From_Stream()
{
    uint32_t fifoleavesize=0;
	static  uint32_t prefifoleavesize=0 ;
	static  uint32_t precheck_idex=0 ,check_idex=0;
	int key;
	uint32_t framelen=0;
	uint16_t msg_id = 0;
	pthread_mutex_lock(&rx_buf_stream_mut);
    fifoleavesize = get_leavesave(rx_buf_stream) ;
    pthread_mutex_unlock(&rx_buf_stream_mut);

    if(fifoleavesize < SYNC_HEADLEN)
	{
		usleep(100);
		return;
    }
	pthread_mutex_lock(&rx_buf_stream_mut);
    key = PF_Parser_Find_Sync_Head(fifoleavesize,0);
    pthread_mutex_unlock(&rx_buf_stream_mut);

    if(key<0)
    {
       pthread_mutex_lock(&rx_buf_stream_mut);
       move_rbuf_len(rx_buf_stream,skip_nbyte_find_head);
       pthread_mutex_unlock(&rx_buf_stream_mut);
       return;
    }

    if(skip_nbyte_find_head > 0)
    {
    	pthread_mutex_lock(&rx_buf_stream_mut);
		move_rbuf_len(rx_buf_stream,skip_nbyte_find_head);

        pthread_mutex_unlock(&rx_buf_stream_mut);
		prefifoleavesize = fifoleavesize;
		precheck_idex = check_idex;

		parser_skip_frm_cnt++;
		if(parser_skip_frm_cnt >= 10)
		{
			parser_skip_frm_cnt = 0;
		}
		usleep(100);
		return;
    }
    if(SYNC_HEADLEN > fifoleavesize-skip_nbyte_find_head)
    {
    	PRINT_INFO("fifoleavesize =%u skip_nbyte_find_head=%u SYNC_HEADLEN=%d  \n",fifoleavesize,skip_nbyte_find_head,SYNC_HEADLEN);
        return;
    }
	pthread_mutex_lock(&rx_buf_stream_mut);
    framelen=   (rx_buf_stream->pdata[MOD_RINGBUF_LEN(rx_buf_stream->pread+HEAD_LEN+0)]<<0)+ \
                (rx_buf_stream->pdata[MOD_RINGBUF_LEN(rx_buf_stream->pread+HEAD_LEN+1)]<<8);
	msg_id = 	(rx_buf_stream->pdata[MOD_RINGBUF_LEN(rx_buf_stream->pread+HEAD_LEN+2)]<<0)+ \
                (rx_buf_stream->pdata[MOD_RINGBUF_LEN(rx_buf_stream->pread+HEAD_LEN+3)]<<8);
	pthread_mutex_unlock(&rx_buf_stream_mut);
	if(SYNC_HEADLEN +skip_nbyte_find_head+framelen> fifoleavesize)
    {
    	usleep(100);
        return;
    }
	if(framelen==0){
		pthread_mutex_lock(&rx_buf_stream_mut);
		reset_rbuf(rx_buf_stream);
		prefifoleavesize =0;
		fifoleavesize=0;
        //move_rbuf_len(rx_buf_stream,fifoleavesize-skip_nbyte_find_head);
        pthread_mutex_unlock(&rx_buf_stream_mut);
		PRINT_INFO("framelen is %u  \n",framelen);
		usleep(100);
        return;
	}

	if(framelen > FRAME_MAX_LEN)
    {
        pthread_mutex_lock(&rx_buf_stream_mut);
        move_rbuf_len(rx_buf_stream,fifoleavesize-skip_nbyte_find_head);
        pthread_mutex_unlock(&rx_buf_stream_mut);
		PRINT_INFO("framelen is too large =%u  \n",framelen);
		usleep(100);
        return;
    }
    if(framelen> (fifoleavesize-skip_nbyte_find_head))
    {
    	usleep(100);
        return;
    }

	pthread_mutex_lock(&rx_buf_stream_mut);
	move_rbuf_len(rx_buf_stream,SYNC_HEADLEN);
    read_rbuf(rx_buf_stream,buf,framelen);
	pthread_mutex_unlock(&rx_buf_stream_mut);

	xdata_rx_callback(buf, framelen, msg_id);

	total_rx_pkt_num_payload++;
	total_rx_dat_len_payload+=framelen;
	total_rx_pkt_num_payload_g++;
	total_rx_dat_len_payload_g+=framelen;

	parser_skip_frm_cnt=0;
}

void PF_Parser_On_Event(uint8_t* data, uint32_t len)
{
    if(!data) {
		return;
	}

	pthread_mutex_lock(&rx_buf_stream_mut);
	write_rbuf(rx_buf_stream, data, len);
	pthread_mutex_unlock(&rx_buf_stream_mut);
}

void *PF_Parser_Thread(void* args)
{
	char achName[64];

	//set thread name
	sprintf(achName, "BB_parser");
    prctl(PR_SET_NAME, achName, 0, 0, 0);

	while(1)
	{
		if(0==parser_exit)
		{
            PF_Parser_Find_Packet_From_Stream();
		}
		else
		{
			PRINT_INFO("%s exit\n", __FUNCTION__);
			break;
		}
	}
	return NULL;
}

int PF_Parser_Init(unsigned  int rx_buf_len)
{
	pthread_mutexattr_t attr;
	int s32Ret;

    rx_buf_stream = (ringbuf*)malloc(sizeof(ringbuf));
    if(rbuf_initial(rx_buf_stream,rx_buf_len) < 0)
	{
		return (0);
	}
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
	pthread_mutex_init(&rx_buf_stream_mut, &attr);


	parser_exit=0;
	s32Ret = MID_UTIL_CreateDetachThread(PF_Parser_Thread,NULL, NULL);
	if(s32Ret < 0)
	{
		PRINT_ERR("PF_Parser_Init fail");
		return -1;
	}
    return 1;
}

void PF_Parser_Deinit()
{
	PRINT_INFO("Parser deinit");
	parser_exit=1;
    rbuf_uninitial(rx_buf_stream);
	free(rx_buf_stream);
	pthread_mutex_destroy(&rx_buf_stream_mut);
}
